Skip to content

Add one-click Easy-Install for automatic dependency management#439

Open
yvann-ba wants to merge 2 commits intosemiautomaticgit:masterfrom
yvann-ba:feature/easy-install
Open

Add one-click Easy-Install for automatic dependency management#439
yvann-ba wants to merge 2 commits intosemiautomaticgit:masterfrom
yvann-ba:feature/easy-install

Conversation

@yvann-ba
Copy link
Copy Markdown

@yvann-ba yvann-ba commented Apr 7, 2026

Summary

This PR adds a complete one-click dependency auto-installer (Easy-Install) that automatically downloads and configures all required Python packages in an isolated virtual environment when the plugin is first loaded.

Problem

Users currently need to manually install scipy, scikit-learn, matplotlib, torch, and torchvision before using SCP. The existing mechanism only handles remotior-sensus via a tarball download. This is a significant barrier for non-technical users.

Solution

  • On plugin load, a fast filesystem check (no subprocess) determines if dependencies are present
  • If missing, a lightweight stub plugin shows a non-blocking install dialog
  • The dialog runs the full setup in a background QThread — QGIS stays fully responsive
  • All packages are installed into an isolated venv at ~/.scp_dependencies/
  • Uses uv for 2-3x faster installs (falls back to pip)
  • Downloads a standalone Python matching the QGIS version for reliable venv creation
  • Comprehensive error handling: SSL errors, proxy settings, antivirus blocks, network retries, Windows DLL issues

What's included

5 new files in core/:

File Purpose
scp_config.py Configuration constants (packages, versions, cache dir)
python_manager.py Downloads standalone Python from python-build-standalone
uv_manager.py Downloads/manages uv package installer
venv_manager.py Venv creation, batch install, verification, numpy/typing_extensions conflict handling
install_dialog.py Non-blocking PyQt6 dialog with progress bar

Modified files:

File Change
__init__.py Added stub plugin pattern with dependency gating
semiautomaticclassificationplugin.py Simplified remotior-sensus import (old download mechanism removed)
metadata.txt Changelog entry
requirements.txt Complete dependency list including matplotlib and remotior-sensus

Key design decisions

  • Non-blocking UI: QThread-based — QGIS never locks up during download/install
  • Batch installation: uv installs PyPI packages in 1 command + torch in another (2 instead of 6)
  • Isolated venv: Dependencies don't affect system Python or QGIS internals
  • CPU-only torch: Always uses CPU index to avoid CUDA complexity
  • Hash-based invalidation: Detects when package requirements or install logic change
  • Cross-platform: Tested patterns for Linux, macOS (arm64/x86_64), and Windows
  • PYTHONPATH for multiprocessing: Ensures spawned child processes can find venv packages
  • Cache customization: Users can override the install directory via SCP_CACHE_DIR environment variable

Compatibility

  • QGIS 4 (3.99+) with PyQt6 — matches v9.0.0 requirements
  • Python 3.9+ (matching QGIS bundle)
  • Linux, macOS, Windows

Test plan

  • Fresh install: Remove ~/.scp_dependencies/, start QGIS → stub shows → click Install → all deps install → restart QGIS → plugin loads normally
  • Already installed: With deps present, verify QGIS starts with the full plugin immediately (no dialog)
  • Network failure: Disconnect during install → verify graceful error message in dialog
  • Version mismatch: Bump INSTALL_LOGIC_VERSION → restart → verify re-install triggers
  • Cross-platform: Test on Linux, macOS, Windows

Easy-Install feature contributed by TerraLab

yvann-ba added 2 commits April 7, 2026 11:31
Add a complete dependency auto-installer that downloads and configures
all required Python packages (remotior-sensus, scipy, scikit-learn,
matplotlib, torch CPU, torchvision) in an isolated virtual environment.

On plugin load, a fast filesystem check determines if dependencies are
present. If missing, a lightweight stub plugin shows a non-blocking
install dialog that handles the full setup in a background thread:

- Downloads a standalone Python matching the QGIS version
- Downloads the uv package installer for faster installs
- Creates an isolated venv at ~/.scp_dependencies/
- Batch-installs all packages (2 commands via uv, fallback to pip)
- Verifies each package after installation
- Handles SSL errors, proxy settings, antivirus blocks, and more

The previous remotior_sensus-only download mechanism in
semiautomaticclassificationplugin.py is replaced by this unified
approach that covers all dependencies.

New files:
  core/scp_config.py      - Configuration constants
  core/python_manager.py   - Standalone Python download
  core/uv_manager.py       - uv package installer download
  core/venv_manager.py     - Venv creation, install, verification
  core/install_dialog.py   - Non-blocking Qt6 install dialog

Modified files:
  __init__.py              - Stub plugin pattern with dep gating
  semiautomaticclassificationplugin.py - Simplified RS import
  metadata.txt             - Changelog entry
  requirements.txt         - Complete dependency list

Easy-Install feature contributed by TerraLab (https://terralab.fr)
@yvann-ba
Copy link
Copy Markdown
Author

@semiautomaticgit hope you're doing well, just ping your username in case you didn't see this pr, have a great day

@semiautomaticgit
Copy link
Copy Markdown
Owner

Dear @yvann-ba ,

first of all thank you very much for your work, it is much appreciated!
I understand that dependency management in QGIS plugins is a complex topic, especially when dealing with large scientific stacks such as PyTorch and related libraries.

However I have a few concerns about your current approach, mainly around how the virtual environment is integrated into QGIS at runtime.
In particular, QGIS developers have historically been cautious about the installation of additional packages (see: https://lists.osgeo.org/pipermail/qgis-developer/2024-October/067097.html).

The main point is that the current implementation modifies Python import-related state (e.g., sys.path, sys.modules) inside the running QGIS process.
Even if this is intended to be scoped to SCP, it still changes the interpreter’s import resolution behavior during runtime, which can introduce subtle risks in long-running sessions. This pattern becomes more critical when introducing widely used scientific dependencies such as PyTorch, where version conflicts and shared imports are more likely to have cross-plugin impact.

In particular:

  • Injecting venv site-packages into sys.path changes module resolution order for the current session.
  • Reloading or replacing modules such as numpy or typing_extensions at runtime can be fragile if those modules are already imported elsewhere, potentially leading to inconsistent state in the interpreter.

Additionally, I would like to highlight a separate security concern regarding the use of flags such as --allow-insecure-host in the installation process (used with uv). Disabling TLS verification for package hosts reduces the integrity guarantees of dependency downloads, and may expose the installation process to man-in-the-middle or package substitution risks, especially in environments where users are on untrusted or intercepted networks.

From a QGIS architecture perspective, a potentially safer direction could be to isolate dependency execution via a subprocess-based approach using the venv Python interpreter. This would avoid modifying the running QGIS interpreter state, although I realize it would likely require a more substantial refactor of the current execution flow.

Thanks again for the contribution, and happy to discuss further.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants